/////////////////////////////////////////////
// ObjectARX defined commands

#include "StdAfx.h"
#include "StdArx.h"
#include "GeAssign.h"


// This is command 'CIR'
void cir()
{
	AcDbDatabase *pCurDb;
	AcDbBlockTable *pBlkTable;
	AcDbBlockTableRecord *pBlkTableRec;
	AcDbObjectId circId;

	AcDbCircle *pCirc;

	AcGePoint3d cen;
	AcGeVector3d normal(0.0, 0.0, 1.0);	// Plane orientation
	ads_point cp;
	double rad;

	acedInitGet(RSG_NONULL, NULL);
	acedGetPoint(NULL, "\nPick circle center point: ", cp);
	cen = asPnt3d(cp);	// convert the ads_point to AcGePoint3d

	acedInitGet(RSG_NONULL + RSG_NOZERO + RSG_NONEG, NULL);
	acedGetDist(cp, "\nCircle radius: ", &rad);

	// Create the circle entity
	pCirc = new AcDbCircle(cen, normal, rad);


	// We are going to add the entity to the
	// Model Space Block Table Record of the
	// Block Table
	pCurDb = acdbHostApplicationServices()->workingDatabase();
	// Open the Block Table for a read operation
	pCurDb->getBlockTable(pBlkTable, AcDb::kForRead);
	// Get the Model Space Block Table record of the Block Table
	pBlkTable->getAt(ACDB_MODEL_SPACE, pBlkTableRec, AcDb::kForWrite);
	// Add the newly crated circle entity to the
	// Block Table Record
	pBlkTableRec->appendAcDbEntity(circId, pCirc);


	// Close the Block Table, the Block Table Record
	// and the Entity

	pBlkTable->close();
	pBlkTableRec->close();
	pCirc->close();

}

// This is command 'LIN'
void lin()
{
	AcDbDatabase *pCurDb;
	AcDbBlockTable *pBlkTable;
	AcDbBlockTableRecord *pBlkTableRec;
	AcDbObjectId lineId;

	AcDbLine *pLn;

	AcGePoint3d sp, ep;

	acedInitGet(RSG_NONULL, NULL);
	// Note how we convert an ads_point to a AcGePoint3d
	// using the mechanism (double*)(&point)
	acedGetPoint(NULL, "\nPick line start point: ", (double*)(&sp));

	acedInitGet(RSG_NONULL, NULL);
	acedGetPoint((double*)(&sp), "\nPick line end point: ", (double*)(&ep));

	// Create the line entity
	pLn = new AcDbLine(sp, ep);


	// We are going to add the entity to the
	// Model Space Block Table Record of the
	// Block Table
	pCurDb = acdbHostApplicationServices()->workingDatabase();
	// Open the Block Table for a read operation
	pCurDb->getBlockTable(pBlkTable, AcDb::kForRead);
	// Get the Model Space Block Table record of the Block Table
	pBlkTable->getAt(ACDB_MODEL_SPACE, pBlkTableRec, AcDb::kForWrite);
	// Add the newly crated circle entity to the
	// Block Table Record
	pBlkTableRec->appendAcDbEntity(lineId, pLn);


	// Close the Block Table, the Block Table record
	// and the enity

	pBlkTable->close();
	pBlkTableRec->close();
	pLn->close();
}

// This is command 'ARK'
void ark()
{
	AcDbDatabase *pCurDb;
	AcDbBlockTable *pBlkTable;
	AcDbBlockTableRecord *pBlkTableRec;
	AcDbObjectId arkId;
	AcDbArc *pArc;

	// The AcDbArc constructors deal in terms of
	// a center point, start angle, end angle and
	// radius. There are no constructors for 3 point
	// arcs. The AcGe geometry classes allows us to
	// create a mathematical arc using 3 points from
	// which we can get the center, radius and 
	// calculate the start and end angles. 

	AcGePoint2d p1, p2, p3, cen;	// location points
	AcGePoint3d cenark;				// center location
	AcGeLine2d lineEnt;	// 2d infinite line
	AcGeTol tol;		// tolerance used by isOn() function
	double rad, eang, sang;

	ads_point sp, ap, ep;

	acedInitGet(RSG_NONULL, NULL);
	acedGetPoint(NULL, "\nPick arc start point: ", sp);
	acedInitGet(RSG_NONULL, NULL);
	acedGetPoint(sp, "\nPick second point of arc: ", ap);
	acedGrDraw(sp, ap, 1, 0);
	// acedGrDraw draws temporary vectors from
	// start point to end point in color, with/without highlight
	acedInitGet(RSG_NONULL, NULL);
	acedGetPoint(ap, "\nPick arc end point: ", ep);
	acedGrDraw(ap, ep, 1, 0);

	p1[X] = sp[X];
	p1[Y] = sp[Y];

	p2[X] = ap[X];
	p2[Y] = ap[Y];

	p3[X] = ep[X];
	p3[Y] = ep[Y];

	lineEnt.set(p1, p3);	// create the infinite mathematical line

	// Create the mathematical arc
	AcGeCircArc2d geark(p1, p2, p3);
	rad = geark.radius();
	cen = geark.center();

	cenark.set(cen[X], cen[Y], 0.0);

	tol.setEqualPoint(0.001);	// set tolerance value
								// default is 1.e-10

	// Look at how we test to see if geometry point
	// p2 in on the infinite line defined by p1 and p3
	if(lineEnt.isOn(p2, tol))
	{
		acutPrintf("\nPoints picked are colinear - invalid arc. ");
		return;
	}


	// Calculate the start and end angles
	// Notice how we convert the AcGePoint2d to
	// an ads_point using the cast mechanism
	// (double*) (&point)
	sang = acutAngle((double*) (&cen), sp);
	eang = acutAngle((double*) (&cen), ep);


	// Dependant on the arc direction switch
	// the start and end angles
	if(geark.isClockWise())
	{
		pArc = new AcDbArc(cenark, rad, eang, sang);
	}
	else
	{
		pArc = new AcDbArc(cenark, rad, sang, eang);
	}

	pCurDb = acdbHostApplicationServices()->workingDatabase();
	pCurDb->getBlockTable(pBlkTable, AcDb::kForRead);
	pBlkTable->getAt(ACDB_MODEL_SPACE, pBlkTableRec, AcDb::kForWrite);
	pBlkTableRec->appendAcDbEntity(arkId, pArc);

	pBlkTableRec->close();
	pBlkTable->close();
	pArc->close();
}

